#include <QApplication>
#include <QDebug>
#include <QDBusInterface>
#include <QDBusArgument>
#include <QDBusMetaType>
#include <QThread>


#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
#define FCITX_DBUS_PATH "/inputmethod"
#define FCITX_DBUS_INF "org.fcitx.Fcitx.InputMethod"
#define DBUS_PROP_INF "org.freedesktop.DBus.Properties"


struct DBusIMData {
      QString lname;
      QString name;
      QString lang;
      bool    enabled;
};

// Retrieve the DBusIMData data from the D-Bus argument
inline const QDBusArgument &operator>>(const QDBusArgument &argument, DBusIMData &im) {
    argument.beginStructure();
    argument >> im.lname >> im.name >> im.lang >> im.enabled;
    argument.endStructure();
    return argument;
}
inline QDBusArgument &operator<<(QDBusArgument &argument, const DBusIMData &im) {
    argument.beginStructure();
    argument << im.lname << im.name << im.lang << im.enabled;
    argument.endStructure();
    return argument;
}


Q_DECLARE_METATYPE(DBusIMData) //QVariant && register

inline QDebug &operator<<(QDebug &out, const DBusIMData &im) {
    return out << qPrintable(QString("('%1', '%2', '%3', ").arg(im.lname).arg(im.name).arg(im.lang))
               << im.enabled << ")";
}
typedef QList<DBusIMData> DBusIMDataList;


int main(int argc, char** argv) {
    QApplication app(argc, argv);

    qDBusRegisterMetaType<DBusIMData>();
    qDBusRegisterMetaType<DBusIMDataList>();

    QDBusInterface *fcitx_dbus_inf =  new QDBusInterface(FCITX_DBUS_SERVICE, FCITX_DBUS_PATH, DBUS_PROP_INF);
    QDBusInterface *fcitx_dbus_inf2 =  new QDBusInterface(FCITX_DBUS_SERVICE, FCITX_DBUS_PATH, FCITX_DBUS_INF);
    int kbd_cn_idx = -1;
    DBusIMDataList enabledIMList;

    QDBusMessage reply = fcitx_dbus_inf->call("Get", FCITX_DBUS_INF, "IMList");
    if(reply.type() != QDBusMessage::ReplyMessage)
        qCritical() << reply.errorMessage();

    QDBusVariant const &dvar = reply.arguments().at(0).value<QDBusVariant>();
    QDBusArgument const &arg = dvar.variant().value<QDBusArgument>();


    arg.beginArray();
    while(!arg.atEnd()) {
        DBusIMData im;
        arg >> im;
        if(im.enabled) {
            if(im.name == "fcitx-keyboard-cn")
                kbd_cn_idx = enabledIMList.size();
            enabledIMList << im;
        }
    }
    arg.endArray();
    qDebug() << "enabledIMList:" << enabledIMList;
    if(kbd_cn_idx == -1) {
        DBusIMData im = {"键盘 - 汉语", "fcitx-keyboard-cn", "", true};
        enabledIMList.prepend(im);
    }else if(kbd_cn_idx > 0) {
        auto im = enabledIMList[kbd_cn_idx];
        enabledIMList[kbd_cn_idx] = enabledIMList[0];
        enabledIMList[0] = im;
    }
    //添加
    if(kbd_cn_idx != 0) {
            QDBusVariant set_dvar(QVariant::fromValue(enabledIMList));
            fcitx_dbus_inf->call("Set", FCITX_DBUS_INF, "IMList",
                                  QVariant::fromValue(set_dvar));
            //fcitx_dbus_inf2->call("ReloadConfig");
                                  
    }
    QDBusMessage reply2 = fcitx_dbus_inf->call("Get", FCITX_DBUS_INF, "IMList");
    if(reply2.type() != QDBusMessage::ReplyMessage)
        qCritical() << reply2.errorMessage();

    QDBusVariant const &dvar2 = reply2.arguments().at(0).value<QDBusVariant>();
    QDBusArgument const &arg2 = dvar2.variant().value<QDBusArgument>();

    enabledIMList.clear();
    arg2.beginArray();
    while(!arg2.atEnd()) {
        DBusIMData im;
        arg2 >> im;
        if(im.enabled) {
            enabledIMList << im;
        }
    }
    arg2.endArray();
    qDebug() << "enabledIMList:" << enabledIMList;
    return app.exec();

}
